package com.fulu.game.bi.common.util.csv;

import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * @Author libo
 * @date 2020/9/1 5:11 PM
 */
@Slf4j
public final class CsvExportUtil {

    private CsvExportUtil() {
    }

    public static void export(String fileName, List<String> header, List<List<String>> content) {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setContentType("application/x-download");
        try {
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8),
                            "ISO8859-1") + ".csv");
        } catch (UnsupportedEncodingException e) {
            response.addHeader("Content-Disposition", "attachment;filename=export_result.csv");
        }
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        try (ServletOutputStream writer = response.getOutputStream()) {
            writer.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
            writeLine(writer, header.toArray(new String[0]));
            content.forEach(c -> writeLine(writer, c.toArray(new String[0])));
            writer.flush();
        } catch (IOException e) {
            log.error("导出文件发生异常", e);
        }
    }


    public static void export(Integer scrollSize,
                              String fileName,
                              Map map,
                              Querier query) {
        int pageNum = 1;
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setContentType("application/x-download");
        try {
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8),
                            "ISO8859-1") + ".csv");
        } catch (UnsupportedEncodingException e) {
            response.addHeader("Content-Disposition", "attachment;filename=export_result.csv");
        }
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());


        try (
                ServletOutputStream writer = response.getOutputStream();
        ) {
            writer.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});

            Set<String> set = map.keySet();
            writeLine(writer, set.toArray(new String[0]));

            boolean hasMore = true;
            long currentIndex = 0;
            while (hasMore) {

                PageInfo page = query.nextPage(pageNum);

                page.getList().forEach(v -> {
                    Collection<Mapper> values = map.values();
                    String[] array = values.stream()
                            .map(mapper1 -> mapper1.value(v))
                            .collect(Collectors.toList())
                            .toArray(new String[1]);
                    writeLine(writer, array);
                });
                writer.flush();

                currentIndex += scrollSize;
                long total = page.getTotal();

                log.info("导出进度 : {} / {} ", currentIndex < total ? currentIndex : total, total);

                // 刷新状态
                hasMore = page.isHasNextPage();
                pageNum++;
            }
        } catch (IOException e) {
            log.error("导出文件发生异常", e);
        }
    }

    public static void writeLine(OutputStream writer, String[] line) throws RuntimeException {
        try {
            StringJoiner stringJoiner = new StringJoiner(",");
            Arrays.stream(line)
                    .map(v -> v == null ? "" : "\"" + v + "\"")
                    .forEach(stringJoiner::add);

            log.debug(stringJoiner.toString());
            String s = stringJoiner.toString().replaceAll("\\n", "") + "\n";
            writer.write(s.getBytes());

        } catch (IOException e) {
            log.error("写出文件异常", e);
            throw new RuntimeException("写出文件异常");//NOPMD
        }
    }
}
